﻿using System;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using Shield.HTTPModule.Properties;

namespace Shield.HTTPModule
{
    public class RequestDeflector : IHttpModule, IRequestDeflector
    {
        private StringCollection _blacklist;
        private string _errorURL;
        private StringCollection _whitelist;

        #region IHttpModule Members

        public void Dispose()
        {
            //throw new NotImplementedException();
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += context_BeginRequest;
        }

        #endregion

        #region IRequestDeflector Members

        public StringCollection Blacklist
        {
            get
            {
                _blacklist = Settings.Default.Blacklist;
                return _blacklist;
            }
            set { throw new NotImplementedException(); }
        }

        public StringCollection Whitelist
        {
            get
            {
                _whitelist = Settings.Default.Whitelist;
                return _whitelist;
            }
            set { throw new NotImplementedException(); }
        }

        public RequestDeflectorType Mode
        {
            get
            {
                int modeValue = Settings.Default.Mode;
                switch (modeValue)
                {
                    case 1:
                        return RequestDeflectorType.Restrictive;
                    case 2:
                        return RequestDeflectorType.Permissive;
                    default:
                        return RequestDeflectorType.Restrictive;
                }
            }
            set { throw new NotImplementedException(); }
        }


        public string ErrorURL
        {
            get
            {
                _errorURL = Settings.Default.ErrorURL;
                return _errorURL;
            }
            set { throw new NotImplementedException(); }
        }

        #endregion

        private void context_BeginRequest(object sender, EventArgs e)
        {
            if (sender == null) return;
            HttpRequest Request = ((HttpApplication) sender).Context.Request;

            foreach (string key in Request.QueryString)
                if (!Whitelist.Contains(key))
                CheckHTML(Request.QueryString[key]);
            
            foreach (string key in Request.Form)
                if (!Whitelist.Contains(key))
                CheckHTML(Request.Form[key]);
            foreach (string key in Request.Cookies)
// ReSharper disable PossibleNullReferenceException
                if (Request.Cookies != null)
                    if (!Whitelist.Contains(key))
                    CheckHTML(Request.Cookies[key].Value);
// ReSharper restore PossibleNullReferenceException
        }

        public void CheckHTML(string param)
        {
            if (Mode == RequestDeflectorType.Restrictive)
                for (int i = 0; i < Blacklist.Count; i++)
                {
                    if (param.IndexOf(Blacklist[i], StringComparison.OrdinalIgnoreCase) >= 0)
                        HttpContext.Current.Response.Redirect(ErrorURL);
                }
        }

        private static string EncodeHTML(string param)
        {
            var builder = new StringBuilder("", param.Length*2);

            foreach (char ch in param)
            {
                if ((((ch <= '`') || (ch >= '{')) && ((ch <= '@') || (ch >= '['))) &&
                    (((ch != ' ') && ((ch <= '/') || (ch >= ':'))) &&
                     (((ch != '.') && (ch != ',')) && ((ch != '-') && (ch != '_')))))
                {
                    builder.Append("&#" + ((int) ch) + ";");
                }
                else
                {
                    builder.Append(ch);
                }
            }

            return builder.ToString();
        }
    }
}